import { isFunction } from "./mountElement";
import mountNativeElement from "./mountNativeElement";
/**
 * 渲染组件，并挂载到container上
 * @param {*} vDom 
 * @param {*} container 
 * @param {*} oldDom 
 */
export default function mountComponent(vDom, container, oldDom) {
  let nextVDom = null
  let component = null
  // 区分组件是函数组件还是类组件
  if (isFunctionComponent(vDom)) {
    nextVDom = buildFunctionComponent(vDom)
  } else {
    nextVDom = buildClassComponent(vDom)
    component = nextVDom.component
  }
  if (component) {
    if (component.props && component.props.ref)
      component.props.ref(component)
  }
  // 如果组件的vDom也是一个组件，则递归调用mountComponent去渲染
  if (isFunction(nextVDom)) {
    mountComponent(nextVDom, container, oldDom)
  } else {
    mountNativeElement(nextVDom, container, oldDom)
  }
}

export function isFunctionComponent(vDom) {
  // 如果vDom的type属性是一个函数，且这个函数的原型中有render方法，则认为它是一个类组件
  const type = vDom.type
  return type && isFunction(vDom) && !(type.prototype?.render)
}

// 返回vDom的type，也就是获取组件的VDom
export function buildFunctionComponent(vDom) {
  return vDom.type(vDom.props || {})
}

// 获取类组件的vDom，需要通过调用其示例的render方法
export function buildClassComponent(vDom) {
  // 传入props
  const component = new vDom.type(vDom.props || {})
  const nextVDom = component.render()
  // 将component实例作为vDom的一个属性导出
  nextVDom.component = component
  return nextVDom
}